/**
 ***********************************************************************************************************
 * 
 ***********************************************************************************************************
 * @file RBMatrix.h
 ***********************************************************************************************************/

#ifndef __RBMATRIX_H__
#define __RBMATRIX_H__

#ifdef  HEADER_ONCE
#pragma HEADER_ONCE
#endif

#ifdef  HEADER_MSG
#pragma HEADER_MSG(RBMatrix.h)
#endif

/***********************************************************************************************************
 * Includes
 ***********************************************************************************************************/
#include <RBMain/RBVector.h>

/***********************************************************************************************************
 * Forward declarations
 ***********************************************************************************************************/

/***********************************************************************************************************
 * Classes
 ***********************************************************************************************************/

template<typename Type, uint32 Rows, uint32 Cols>
class RBMatrix
{
    typedef RBMatrix<Type, Rows, Cols> ThisType;
public:
                        RBMatrix    ();
                        RBMatrix    (Type scalar);
                        RBMatrix    (Type m00, Type m01, Type m02,
                                     Type m10, Type m11, Type m12,
                                     Type m20, Type m21, Type m22);

                        RBMatrix    (Type m00, Type m01, Type m02, Type m03,
                                     Type m10, Type m11, Type m12, Type m13,
                                     Type m20, Type m21, Type m22, Type m23,
                                     Type m30, Type m31, Type m32, Type m33);

                       ~RBMatrix    ();

    static const ThisType& Identity    ();
    void                SetIdentity ();

    ThisType            Transpose   () const;

    void                GetCol      (uint8 uiCol, RBVector<Type, Rows>& vec) const;
    void                GetRow      (uint8 uiRow, RBVector<Type, Cols>& vec) const;

    void                SetXRotation(Type xRot);
    void                SetYRotation(Type yRot);
    void                SetZRotation(Type zRot);

    Type&               operator()  (uint8 uiRow, uint8 uiCol);
    Type                operator()  (uint8 uiRow, uint8 uiCol) const;
    Type                operator()  (uint8 idx) const { return Data[idx]; };
    Type&               operator()  (uint8 idx)       { return Data[idx]; };
    Type*               GetCol      (uint8 uiCol);
    const Type*         GetCol      (uint8 uiCol) const;

    ThisType            operator-	() const;
    ThisType		    operator+	(const ThisType& rhs) const;
    ThisType		    operator-	(const ThisType& rhs) const;
    friend ThisType     operator*	(Type scalar, const ThisType& mat);
    ThisType		    operator*	(const ThisType& rhs) const;
    RBVector<Type,Rows>	operator*	(const RBVector<Type,Cols>& vec) const;
    ThisType&           operator=   (const ThisType& rhs);
    ThisType&           operator+=  (const ThisType& rhs);
    ThisType&           operator-=  (const ThisType& rhs);
    ThisType&           operator*=  (const ThisType& rhs);
    ThisType&           operator*=  (Type scalar);

private:
    Type                Data[Rows*Cols];

};

#include "RBMatrix.inl"

typedef RBMatrix<float,3,3> float3x3;
typedef RBMatrix<float,4,4> float4x4;
typedef RBMatrix<float,4,3> float4x3;
typedef RBMatrix<float,3,4> float3x4;

/***********************************************************************************************************/

#endif // __RBMATRIX_H__
